

# gcc编译器名称前缀
ifeq ($(PREFIX),)
PREFIX = arm-none-eabi-
endif

# mcu芯片类型，参看 CMSIS 中的文件 "stm32f10x.h"
# STM32F103x4 ( 16KiB FLASH,  6KiB RAM)					--> STM32F10X_LD
# STM32F103x6 ( 32KiB FLASH, 10KiB RAM)					--> STM32F10X_LD
# STM32F103x8 ( 64KiB FLASH, 20KiB RAM)					--> STM32F10X_MD
# STM32F103xB (128KiB FLASH, 20KiB RAM)					--> STM32F10X_MD
# STM32F103xC (256KiB FLASH, 48KiB RAM)					--> STM32F10X_HD
# STM32F103xD (384KiB FLASH, 64KiB RAM)					--> STM32F10X_HD
# STM32F103xE (512KiB FLASH, 64KiB RAM)					--> STM32F10X_HD
# STM32F103xF (768KiB FLASH, 96KiB RAM)					--> STM32F10X_XL
# STM32F103xG (  1MiB FLASH, 96KiB RAM)					--> STM32F10X_XL
ifeq ($(TypeOfMcu),)
TypeOfMcu = STM32F103x8
FamilyOfMcu = STM32F10X_MD
else ifeq ($(TypeOfMcu), STM32F103x4)
FamilyOfMcu = STM32F10X_LD
else ifeq ($(TypeOfMcu), STM32F103x6)
FamilyOfMcu = STM32F10X_LD
else ifeq ($(TypeOfMcu), STM32F103x8)
FamilyOfMcu = STM32F10X_MD
else ifeq ($(TypeOfMcu), STM32F103xB)
FamilyOfMcu = STM32F10X_MD
else ifeq ($(TypeOfMcu), STM32F103xC)
FamilyOfMcu = STM32F10X_HD
else ifeq ($(TypeOfMcu), STM32F103xD)
FamilyOfMcu = STM32F10X_HD
else ifeq ($(TypeOfMcu), STM32F103xE)
FamilyOfMcu = STM32F10X_HD
else ifeq ($(TypeOfMcu), STM32F103xF)
FamilyOfMcu = STM32F10X_XL
else ifeq ($(TypeOfMcu), STM32F103xG)
FamilyOfMcu = STM32F10X_XL
else
FamilyOfMcu = unknown
endif

# 目标文件名
TARGET_BASE_NAME = main

# 编译器优化级别设置：
# -O0: 不优化，方便进行调试。
# -O1: 减少代码大小和执行时间。
# -O2: 与'O1'相比，减少代码执行时间。
# -O3: 打开所有优化。
# -Os: 在'O2'的基础上优化代码大小。默认
# 调试时建议设置优化选项为： -O0
# 发布时建议设置优化选项为： -O2/-Os
# 注意： 不是所有工程都适合开启优化。有时开启了优化可能会出现意想不到的问题。
ifeq ($(OPTLVL),)
OPTLVL = -Os
endif

# 可执行程序的向量表的偏移量。值必须是 0x200 的整数倍
ifeq ($(VECT_TAB_OFFSET),)
VECT_TAB_OFFSET = 0
endif


export PREFIX
export FamilyOfMcu
export OPTLVL
export VECT_TAB_OFFSET
#export TOP=$(shell readlink -f "$(dir $(lastword $(MAKEFILE_LIST)))")
export TOP=$(shell pwd)
export RULES := $(TOP)/Rules
include $(RULES)/defs.common.mk



PROGRAM = $(BINDIR)/$(TARGET_BASE_NAME)

# 保存链接脚本的目录
LDSDIR = $(TOP)/ldscript
# 保存MCU的FLASH和RAM信息的链接脚本名
LDS_MEMORY = $(TypeOfMcu)_flash_ram.lds
# 最终参与编译的链接脚本的路经
LDS_FILE = $(OUTS)/linker.lds



LDFLAGS += -Wl,--gc-sections,-L$(LDSDIR),-T$(LDS_FILE),-Map,$(PROGRAM).map
LDFLAGS += -Wl,--whole-archive `cat $(ENTRY_FILE)` -Wl,--no-whole-archive

# 16,10,8进制转10进制 (需要有进制前缀 十六进制为： 0x , 八进制为： 0)
VECT_TAB_OFFSET_CALC := $(shell printf "%d" $(VECT_TAB_OFFSET))

MOD = Src Libraries


all: dep_env dep_dirs targets
	@echo ""
	@echo "目标文件在目录： $(BINDIR)"
	@echo "目标文件 $(PROGRAM).bin 的大小为：" \
		`ls -l $(PROGRAM).bin | awk '{print $$5}'` "字节"

dep_env:
ifneq ($(shell echo "$(VECT_TAB_OFFSET_CALC) % 512" | bc), 0)
	@echo "VECT_TAB_OFFSET($(VECT_TAB_OFFSET)) 不是 512 的整数倍"
	@exit 1
endif
ifeq ($(FamilyOfMcu), unknown)
	@echo "TypeOfMcu 被设置为一个未知值 '$(TypeOfMcu)'"
	@exit 1
endif

dep_dirs:
	@$(MKDIR) $(LIBDIR) $(OBJDIR) $(BINDIR)
	@$(RM) $(LDFLAGS_FILE)*
	@$(TOUCH) $(LDFLAGS_FILE1) $(LDFLAGS_FILE2) $(LDFLAGS_FILE3) $(LDFLAGS_FILE)
	@sed -e \
		's/MEMORY_INFO/$(LDS_MEMORY)/g; s/VECT_OFFSET/$(VECT_TAB_OFFSET)/g' \
		$(LDSDIR)/linker.lds > $(LDS_FILE)

targets: $(MOD)
	@echo "" >> $(LDFLAGS_FILE)
	@echo ""
	$(CC) -o $(PROGRAM).elf $(LDFLAGS) \
		`cat $(LDFLAGS_FILE) $(LDFLAGS_FILE3) $(LDFLAGS_FILE2) $(LDFLAGS_FILE1)`
	$(OBJCOPY) -O ihex $(PROGRAM).elf $(PROGRAM).hex
	$(OBJCOPY) -O binary $(PROGRAM).elf $(PROGRAM).bin
	#Extract info contained in ELF to readable text-files:
	$(READELF) -au $(PROGRAM).elf > $(PROGRAM).info
	$(OBJDUMP) -fxDSlCw $(PROGRAM).elf > $(PROGRAM).lst
#	$(NM) -f posix -lnSs -t x $(PROGRAM).elf > $(PROGRAM).symbol
	$(NM) -f sysv -lnSs -t x $(PROGRAM).elf > $(PROGRAM).symbol
	$(SIZE) -A -x -t --common $(PROGRAM).elf

$(MOD):
	@echo ""
	$(MAKE) -C $@ MOD_NAME=$@

clean:
	@for submod in $(MOD) ; do \
		$(MAKE) -C $$submod MOD_NAME=$$submod $@; \
	done
	@$(RM) $(LDFLAGS_FILE)* $(ENTRY_FILE)

distclean:
	@for submod in $(MOD) ; do \
		$(MAKE) -C $$submod MOD_NAME=$$submod $@; \
	done
	@$(RM) $(OUTS)

.PHONY: all dep_env dep_dirs $(MOD) clean distclean

